package com.ph.shopping.facade.pay.service.impl;

import com.ph.shopping.facade.mapper.MemberDrawcashRecordMapper;
import com.ph.shopping.facade.mapper.UserBalanceMapper;
import com.ph.shopping.facade.mapper.UserBalanceRecordMapper;
import com.ph.shopping.facade.merchant.entity.UserBalance;
import com.ph.shopping.facade.pay.bean.BodyInfo;
import com.ph.shopping.facade.pay.bean.MsgBean;
import com.ph.shopping.facade.pay.bean.MsgBody;
import com.ph.shopping.facade.pay.encrypt.RSA;
import com.ph.shopping.facade.pay.encrypt.TripleDes;
import com.ph.shopping.facade.pay.entity.MemberDrawcashRecord;
import com.ph.shopping.facade.pay.service.IDrawcashService;
import com.ph.shopping.facade.pay.utils.SslConnection;
import com.ph.shopping.facade.pay.utils.Strings;
import com.ph.shopping.facade.pay.utils.UniqueUtils;
import com.ph.shopping.facade.pay.utils.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.util.Date;
import java.util.List;

/**
 * @项目：phshopping-facade-pay
 * @描述：
 * @作者： 张霞
 * @创建时间： 18:45 2017/4/6
 * @Copyright @2017 by zhangxia
 */
@Service
public class DrawcashServiceImpl implements IDrawcashService{
    // 创建公共日志
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private MemberDrawcashRecordMapper memberDrawcashRecordMapper;
    @Autowired
    private UserBalanceMapper userBalanceMapper; //更新余额
    @Autowired
    private UserBalanceRecordMapper userBalanceRecordMapper;//提现记录

    //测试环境
//    private static String dna_pub_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqWSfUW3fSyoOYzOG8joy3xldpBanLVg8gEDcvm9KxVjqvA/qJI7y0Rmkc1I7l9vAfWtNzphMC+wlulpaAsa/4PbfVj+WhoNQyhG+m4sP27BA8xuevNT9/W7/2ZVk4324NSowwWkaqo1yuZe1wQMcVhROz2h+g7j/uZD0fiCokWwIDAQAB";//商户公钥
//    private static String mer_pfx_key = "g:\\daifu\\yilian.pfx";//商户私钥
//    private static String mer_pfx_pass = "11111111";//商户私钥密码
//    private static String url = "https://testagent.payeco.com:9444/service";//测试环境下单地址
//    private static String user_name="13728096874";//系统后台登录名
    //正式环境
    private static String dna_pub_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc+L2JGUKlGtsFm2f/wuF2T6/8mc6yrN8tLPgsx7sxAatvMvunHLXKC8xjkChHqVfJgohV4OIWe8zCw7jPsJMiPvrNnFHJ2Mumg/zQ8eZOnzMA0LDqBNFvZnOpy2XtagQn4yxxzG9+9h4P5eNojC3vD2t3H/6q5V3Cd022/egIZQIDAQAB";//商户公钥
    private static String mer_pfx_key = "g:\\daifu\\104000000072340-Signature.pfx";//商户私钥
    private static String mer_pfx_pass = "88410310";//商户私钥密码
	private static String url = "https://agent.payeco.com/service";//生产环境下单地址
    private static String user_name="13693334601";//系统后台登录名
    //通用环境
    private static String version="2.1";//版本号
    private static String msg_type_dfbm = "100001";//"代付"消息类型的编码
    private static String msg_type_dfcxbm = "100002";//"代付查询结果"消息类型的编码

    /**
     * 代付
     * @param bodyInfo 请求代付基本信息
     * @return 批次号
     * @throws Exception
     */
    @Override
    public String drawcash(BodyInfo bodyInfo) throws Exception {
        logger.info("提现开始请求");
        MsgBean req_bean = new MsgBean();
        req_bean.setVERSION(version);//版本号
        req_bean.setMSG_TYPE(msg_type_dfbm);//消息类型
        req_bean.setBATCH_NO(bodyInfo.getBathNo());//每笔订单不可重复，建议：公司简称缩写+yymmdd+流水号
        req_bean.setUSER_NAME(user_name);//系统后台登录名
        MsgBody body = new MsgBody();
        body.setSN("0000000001");//流水号，同一批次不重复即可
        body.setACC_NO(bodyInfo.getAccNo());//账号
        body.setACC_NAME(bodyInfo.getAccName());
        body.setAMOUNT(bodyInfo.getAmount());//提现金额
		/*body.setACC_PROVINCE("上海市");
		body.setACC_CITY("上海市");*/
        body.setBANK_NAME(bodyInfo.getBankName());
        body.setACC_PROP(bodyInfo.getAccProp());//账号类别,0私人，1公司。默认0
        body.setMER_ORDER_NO(bodyInfo.getMerOrderNo());//商户订单号,商户系统的订单号\保单号
        req_bean.getBODYS().add(body);
        String res = sendAndRead(signANDencrypt(req_bean));
        MsgBean res_bean = decryptANDverify(res);

        if("0000".equals(res_bean.getTRANS_STATE())) {
            logger.info("**代付**批次号:"+req_bean.getBATCH_NO()+"请求成功");
            List<MsgBody> msgBodies = res_bean.getBODYS();
            MsgBody msgBody = msgBodies.get(0);
        }
        logger.info(res_bean.toXml());
        return bodyInfo.getBathNo();
    }

    /**
     * 代付查询结果
     * @param batchNo 代付请求订单号，由代付中获取
     * @param id 数据库中的记录id
     */
    @Override
    public void drawcashQuery(String batchNo,Long id) {
        logger.info("提现结果查询开始请求");
        MsgBean req_bean = new MsgBean();
        req_bean.setVERSION(version);
        req_bean.setMSG_TYPE(msg_type_dfcxbm);
        req_bean.setBATCH_NO(batchNo);//同代付交易请求批次号
        req_bean.setUSER_NAME(user_name);//系统后台登录名

//		MsgBody body = new MsgBody();
//		body.setQUERY_NO_FLAG("0");
//		body.setMER_ORDER_NO("DF123456789");
//		req_bean.getBODYS().add(body);
        String res = sendAndRead(signANDencrypt(req_bean));
        MsgBean res_bean = decryptANDverify(res);
        logger.info(res_bean.toXml());
        if("0000".equals(res_bean.getTRANS_STATE())) {
            logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"请求成功");
            List<MsgBody> msgBodies = req_bean.getBODYS();
            String payState = msgBodies.get(0).getPAY_STATE().trim();
//            if ("0000".equals(payState)){
            if (true){//测试默认成功
                logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"代付成功");
                //处理提现订单状态和会员余额
                updateDrawcashState(id);
            }else if ("00A4".equals(payState)){
                logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"代付订单还在处理中");
            }else {
                logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"代付处理失败");
            }
        }else if("00A4".equals(res_bean.getTRANS_STATE())){
            logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"中间状态，交易状态不明确");
        }else if ("0094".equals(res_bean.getTRANS_STATE())){
            logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"重复交易，Batch_No重复");
        }else {
            logger.info("**代付查询**批次号："+res_bean.getBATCH_NO()+"处理请求失败"+",请求响应状态码："+res_bean.getTRANS_STATE());
        }
    }

    /**
     * 解密
     * @param res
     * @return
     */
    private  MsgBean decryptANDverify(String res) {

        String msg_sign_enc = res.split("\\|")[0];
        String key_3des_enc = res.split("\\|")[1];
        //解密密钥
        String key_3des = RSA.decrypt(key_3des_enc,mer_pfx_key,mer_pfx_pass);
        //解密报文
        String msg_sign = TripleDes.decrypt(key_3des, msg_sign_enc);
        MsgBean res_bean = new MsgBean();
        res_bean.toBean(msg_sign);
        logger.info("res:" + res_bean.toXml());
        //验签
        String dna_sign_msg = res_bean.getMSG_SIGN();
        res_bean.setMSG_SIGN("");
        String verify = Strings.isNullOrEmpty(res_bean.getVERSION())? res_bean.toXml(): res_bean.toSign() ;
        logger.info("verify:" + verify);
        if(!RSA.verify(dna_sign_msg, dna_pub_key, verify)) {
            logger.error("验签失败");
            res_bean.setTRANS_STATE("00A0");
        }
        return res_bean;
    }

    /**
     * 商户签名，加密报文，加密秘钥
     * @param req_bean
     * @return
     */
    private  String signANDencrypt(MsgBean req_bean) {

        //商户签名
        System.out.println("before sign xml =="+ req_bean.toSign());
        System.out.println("msg sign = "+RSA.sign(req_bean.toSign(),mer_pfx_key,mer_pfx_pass));
        req_bean.setMSG_SIGN(RSA.sign(req_bean.toSign(),mer_pfx_key,mer_pfx_pass));
        logger.info("req:" + req_bean.toXml());

        //加密报文
        String key = Util.generateKey(9999,24);
        logger.info("key:" + key);
        String req_body_enc = TripleDes.encrypt(key, req_bean.toXml());
        logger.info("req_body_enc:" + req_body_enc);
        //加密密钥
        String req_key_enc = RSA.encrypt(key, dna_pub_key);
        logger.info("req_key_enc:" + req_key_enc);
        logger.info("signANDencrypt:" + req_body_enc+"|"+req_key_enc);
        return req_body_enc+"|"+req_key_enc;

    }

    /**
     * 发送请求
     * @param req
     * @return
     */
    private String sendAndRead(String req) {

        try {
            HttpURLConnection connect = new SslConnection().openConnection(url);

            connect.setReadTimeout(120000);
            connect.setConnectTimeout(30000);

            connect.setRequestMethod("POST");
            connect.setDoInput(true);
            connect.setDoOutput(true);
            connect.connect();

            byte[] put = req.getBytes("UTF-8");
            connect.getOutputStream().write(put);

            connect.getOutputStream().flush();
            connect.getOutputStream().close();
            String res = SslConnection.read(connect);

            connect.getInputStream().close();
            connect.disconnect();

//			String res = new SslConnection().connect(url);

            return res;
        } catch(Exception e) {
            logger.error(Strings.getStackTrace(e));
        }
        return "";
    }

    /**
     * 处理会员提现后余额更新
     * @param id
     */
    private void updateDrawcashState(Long id){
        MemberDrawcashRecord memberDrawcashRecord = memberDrawcashRecordMapper.selectByPrimaryKey(id);
        Long memberid = memberDrawcashRecord.getMemberId();
//        BigDecimal drawcash = memberDrawcashRecord.getAmount();
        UserBalance userBalance = userBalanceMapper.getUserBalance(memberid);
        Long userBalanceL =  userBalance.getBalance();
        BigDecimal userBalanceD = BigDecimal.valueOf(userBalanceL);
//        BigDecimal resultD = userBalanceD.subtract(drawcash);
//        Long resultL = Long.valueOf(resultD.toString());//最终余额
        //更新用户余额
//        userBalance.setBalance(resultL);
        userBalanceMapper.updateByPrimaryKeySelective(userBalance);
        //更新会员提现记录
        memberDrawcashRecord.setStatus(2);
        memberDrawcashRecord.setUpdateTime(new Date());
        memberDrawcashRecordMapper.updateByPrimaryKeySelective(memberDrawcashRecord);
    }
    public static void main(String[] ars){
        String bathNo = UniqueUtils.getBathNo();
        System.out.println("bathNo = [" + bathNo + "]");
//        BodyInfo bodyInfo = new BodyInfo(UniqueUtils.getBathNo(),"6222033100000756083","田云","10","重庆工商银行朝天门支行","");

    }
}
